package main

import (
	"log"
	"net/http"
	"os"
	"time"
)

// middleware is func
// which need a handler as a param and return a new handler
type middleware func(http.Handler) http.Handler

type Router struct {
	middlewareChain []middleware
	mux             map[string]http.Handler
}

func NewRouter() *Router {
	return &Router{
		mux: make(map[string]http.Handler),
	}
}

func (r *Router) Use(mid middleware) {
	r.middlewareChain = append(r.middlewareChain, mid)
}

func (r *Router) Add(route string, handler http.Handler) {
	var mergeHandler = handler
	for i := len(r.middlewareChain) - 1; i >= 0; i-- {
		mergeHandler = r.middlewareChain[i](mergeHandler)
	}
	r.mux[route] = mergeHandler
}

var logger = log.New(os.Stdout, "", 0)

func hello(wr http.ResponseWriter, r *http.Request) {
	wr.Write([]byte("hello"))
}

func showInfo(wr http.ResponseWriter, r *http.Request) {
	time.Sleep(3 * time.Second)
	wr.Write([]byte("show info"))
}

func timeMiddleware(next http.Handler) http.Handler {
	return http.HandlerFunc(func(wr http.ResponseWriter, r *http.Request) {
		startTime := time.Now()
		next.ServeHTTP(wr, r)
		timeElapsed := time.Since(startTime)
		logger.Println(time.Now(), " timeCost ", timeElapsed)
	})
}

// 所以这个还是得需要一个context参数
func timeout(next http.Handler) http.Handler {
	return http.HandlerFunc(func(wr http.ResponseWriter, r *http.Request) {
		select {
		case <-time.After(2 * time.Second):
			wr.Write([]byte("timeout"))
			return
		}

	})
}

func main() {

	r := NewRouter()
	r.Use(timeMiddleware)
	r.Use(timeout)
	//r.Use(ratelimit)
	r.Add("/hello", http.HandlerFunc(hello))
	r.Add("/show-info", http.HandlerFunc(showInfo))

	for k, v := range r.mux {
		http.Handle(k, v)
	}

	err := http.ListenAndServe(":8088", nil)
	if err != nil {
		log.Fatal(err)
	}
}
